package foo.bar.helloworld;

import org.apache.commons.math3.analysis.BivariateFunction;
import org.apache.commons.math3.analysis.FunctionUtils;
import org.apache.commons.math3.analysis.UnivariateFunction;
import org.apache.commons.math3.analysis.integration.LegendreGaussIntegrator;
import org.apache.commons.math3.analysis.integration.RombergIntegrator;
import org.apache.commons.math3.analysis.integration.SimpsonIntegrator;
import org.apache.commons.math3.analysis.integration.TrapezoidIntegrator;
import org.apache.commons.math3.analysis.polynomials.PolynomialFunction;
import org.apache.commons.math3.complex.Complex;

public class TestCommons {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Complex complex = new Complex(3, 4);
		Complex complex2 = new Complex(3, -4);
		System.out.println("Complex number "+complex);
		System.out.println("Complex number 2"+complex2);
		System.out.println("Absolute number "+complex.abs());	
		System.out.println("Multiply numbers"+complex.multiply(complex2));	
		System.out.println("Add numbers "+complex.add(complex2));	
		
		/* 
		 * f1 - функція з однією змінною; f1 = x*x;
		 */
		UnivariateFunction f1 = new UnivariateFunction() {
			
			@Override
			public double value(double x) {
				// TODO Auto-generated method stub
				return x*x;
			}
		};
		System.out.println("UnivariateFunction f1(3) "+f1.value(3));
		
		/*
		 * f2 - функція з однією змінною; f2 = x*x*x;
		 */
		UnivariateFunction f2 = new UnivariateFunction() {
			
			@Override
			public double value(double x) {
				// TODO Auto-generated method stub
				return x*x*x;
			}
		};
		System.out.println("UnivariateFunction f2(3) "+f2.value(3));
		
		/*
		 * f3 - функція з двома змінними; f3 = x + 2*y;
		 */
		BivariateFunction f3 = new BivariateFunction() {
			
			@Override
			public double value(double x, double y) {
				// TODO Auto-generated method stub
				return x + 2*y;
			}
		};
		System.out.println("BivariateFunction f3(3,4) "+f3.value(3,4));
		
		/*
		 * додавання функцій f4 = f1 + f2;
		 */
		UnivariateFunction f4 = FunctionUtils.add(f1,f2);
		System.out.println("UnivariateFunction f4(3) "+f4.value(3));
		
		/*
		 * множення функцій f5 = f1 * f2; f5 = x*x*x*x*x
		 */
		UnivariateFunction f5 = FunctionUtils.multiply(f1,f2);
		System.out.println("UnivariateFunction f5(3) "+f5.value(3));
		
		/*
		 * комбінація функцій: f6 = f3 = x + 2*y, де x = f1 = t*t,   a y = f2 = t*t*t; t - параметр
		 */
		UnivariateFunction f6 = FunctionUtils.combine(f3, f1, f2);
		System.out.println("UnivariateFunction f6(2) "+f6.value(2));
		
		/*
		 * отримуємо 18 значеь функції f1 = x*x на проміжку [-9,9], точки з кроком (9 - (-9))/18 = 1
		 */
		double[] ds = FunctionUtils.sample(f1, -9, 9, 18);
		for (int i = 0; i < ds.length; i++) {
			System.out.print(ds[i]+" ");
		}
		System.out.println();
		
		/*
		 * Інтегрування за Сімпсоном першої функції в інтервалі від 0 до 3
		 */
		SimpsonIntegrator simpsonIntegrator = new SimpsonIntegrator(SimpsonIntegrator.DEFAULT_RELATIVE_ACCURACY, SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY, SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT, SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT);
		System.out.println("SimpsonIntegrator: Інтеграл f1 = x*x від 0 до 3 = "+simpsonIntegrator.integrate(100, f1, 0, 3));
		
		/*
		 * Інтегрування методом трапеції першої функції в інтервалі від 0 до 3
		 */
		TrapezoidIntegrator trapezoidIntegrator = new TrapezoidIntegrator();
		System.out.println("TrapezoidIntegrator: Інтеграл f1 = x*x від 0 до 3 = "+trapezoidIntegrator.integrate(100000, f1, 0, 3));
		
		/*
		 * Інтегрування методом Ромберга функції в інтервалі від 0 до 3
		 */
		RombergIntegrator rombergIntegrator = new RombergIntegrator();
		System.out.println("RombergIntegrator: Інтеграл f1 = x*x від 0 до 3 = "+rombergIntegrator.integrate(100, f1, 0, 3));
		
		/*
		 * Інтегрування методом Гаусса функції в інтервалі від 0 до 3
		 */
		LegendreGaussIntegrator legendreGaussIntegrator = new LegendreGaussIntegrator(5, LegendreGaussIntegrator.DEFAULT_RELATIVE_ACCURACY, LegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY);
		System.out.println("LegendreGaussIntegrator: Інтеграл f1 = x*x від 0 до 3 = "+legendreGaussIntegrator.integrate(100, f1, 0, 3));
		
		/*
		 * Створення поліному з відповідними коефіцієнтами 
		 */
		PolynomialFunction polynomialFunction = new PolynomialFunction(new double[] {1,2,3,4,5});
		System.out.println("PolynomialFunction "+polynomialFunction.toString());
		System.out.println("polynomialFunction.value(1) = "+polynomialFunction.value(1));
		System.out.println("SimpsonIntegrator: Інтеграл на проміжку [0,3] = "+polynomialFunction.toString()+" = "+simpsonIntegrator.integrate(10000, polynomialFunction, 0, 3));
		System.out.println("Похідна, результат функція: "+polynomialFunction.derivative().toString());
		System.out.println("Похідна, результат поліном: "+polynomialFunction.polynomialDerivative().toString());
	
	}

}
